{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[this doc on github](https://github.com/dotnet/interactive/tree/main/samples/notebooks/csharp/Samples)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "#i \"nuget:https://api.nuget.org/v3/index.json\" \n",
    "#i \"nuget:https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json\" \n",
    "#i \"nuget:https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json\" \n",
    "\n",
    "#r \"nuget:Microsoft.Data.Analysis, 0.21.0\"\n",
    "#r \"nuget: Plotly.NET.Interactive, 4.2.0\"\n",
    "#r \"nuget: Plotly.Net, 4.2.0\"\n",
    "\n",
    "using Microsoft.Data.Analysis;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "DateTimeDataFrameColumn dateTimes = new DateTimeDataFrameColumn(\"DateTimes\"); // Default length is 0.\n",
    "Int32DataFrameColumn ints = new Int32DataFrameColumn(\"Ints\", 6); // Makes a column of length 3. Filled with nulls initially\n",
    "StringDataFrameColumn strings = new StringDataFrameColumn(\"Strings\", 6); // Makes a column of length 3. Filled with nulls initially"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "// Append 6 values to dateTimes\n",
    "dateTimes.Append(DateTime.Parse(\"2019/01/01\"));\n",
    "dateTimes.Append(DateTime.Parse(\"2019/01/01\"));\n",
    "dateTimes.Append(DateTime.Parse(\"2019/01/02\"));\n",
    "dateTimes.Append(DateTime.Parse(\"2019/02/02\"));\n",
    "dateTimes.Append(DateTime.Parse(\"2019/02/02\"));\n",
    "dateTimes.Append(DateTime.Parse(\"2019/03/02\"));"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "DataFrame df = new DataFrame(dateTimes, ints, strings ); // This will throw if the columns are of different lengths"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "// To change a value directly through df\n",
    "df[0, 1] = 10; // 0 is the rowIndex, and 1 is the columnIndex. This sets the 0th value in the Ints columns to 10\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "// Modify ints and strings columns by indexing\n",
    "ints[1] = 24;\n",
    "strings[1] = \"Foo!\";\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "// Indexing can throw when types don't match.\n",
    "// ints[1] = \"this will throw because I am a string\";  \n",
    "// Info can be used to figure out the type of data in a column. \n",
    "df.Info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "// Add 5 to ints through the DataFrame\n",
    "df[\"Ints\"].Add(5, inPlace: true);\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "// We can also use binary operators. Binary operators produce a copy, so assign it back to our Ints column \n",
    "df[\"Ints\"] = (ints / 5) * 20;\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "// Fill nulls in our columns, if any. Ints[2], Strings[0] and Strings[1] are null\n",
    "df[\"Ints\"].FillNulls(100, inPlace: true);\n",
    "df[\"Strings\"].FillNulls(\"Bar\", inPlace: true);\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "// To inspect the first row\n",
    "DataFrameRow row0 = df.Rows[0];\n",
    "row0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "// Filter rows based on equality\n",
    "PrimitiveDataFrameColumn<bool> boolFilter = df[\"Strings\"].ElementwiseEquals(\"Bar\");\n",
    "boolFilter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "DataFrame filtered = df.Filter(boolFilter);\n",
    "filtered"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "// Sort our dataframe using the Ints column\n",
    "DataFrame sorted = df.OrderBy(\"Ints\");\n",
    "sorted"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "//Clone dataframe\n",
    "var newDf = df.Clone();\n",
    "\n",
    "//Add new column\n",
    "StringDataFrameColumn newColumn = new StringDataFrameColumn(\"Month\", ((DateTimeDataFrameColumn)df[\"DateTimes\"]).Select(x => x.Value.ToString(\"MMMM\")));\n",
    "newDf.Columns.Add(newColumn);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "// GroupBy month\n",
    "GroupBy groupBy = newDf.GroupBy(\"Month\");\n",
    "\n",
    "//Show grouped data\n",
    "DataFrame groupedDf = groupBy.Head(10);\n",
    "groupedDf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "// Count of values in each group\n",
    "DataFrame groupCounts = groupBy.Count();\n",
    "groupCounts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "// Alternatively find the sum of the values in each group in Ints\n",
    "DataFrame intsGroupSum = groupBy.Sum(\"Ints\");\n",
    "intsGroupSum"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "using Plotly.NET;\n",
    "using System.Linq;\n",
    "using Microsoft.FSharp.Core;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    },
    "vscode": {
     "languageId": "dotnet-interactive.csharp"
    }
   },
   "outputs": [],
   "source": [
    "display(Chart2D.Chart.Column<int, string, string, string, string>(\n",
    "    ((Int32DataFrameColumn)intsGroupSum[\"Ints\"]).Select(x => x ?? default), new FSharpOption<IEnumerable<string>>(((StringDataFrameColumn)intsGroupSum[\"Month\"]))));"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".NET (C#)",
   "language": "C#",
   "name": ".net-csharp"
  },
  "language_info": {
   "file_extension": ".cs",
   "mimetype": "text/x-csharp",
   "name": "C#",
   "pygments_lexer": "csharp",
   "version": "8.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
